/*
 *  integrator.h
 *  EPPI-0.0
 *
 *  Created by Markus Lutz on 21/11/09.
 *  Modified by JCGO
 *	Modified by Sergio Conde
 *
 */

#ifndef _integrator_h_
#define _integrator_h_

#include <iostream>
#include <map>
#include <vector>
//#include "lmx.h"

using namespace std;


class Simulation;

class Integrator
{
public:

	string type;			// integrator type
	double beta;			// integrator constant (Newmark)
	double gamma;			// integrator constant (Newmark)
	double alpha_f;			// integrator constant (alpha generalized) (Newmark)
	double alpha_m;			// integrator constant (alpha generalized) 
	double rho_inf;			// integrator constant (alpha generalized)

	Simulation *parentSim;    	// pointer to parentSimulation		
	double partial_dq;		// partial derivative of dq_n_1 / q_n_1
	double partial_ddq;		// partial derivative of ddq_n_1 / q_n_1
	double h;			// stepsize

	vector<double> *pq; 	// pointer to position vector in process
	vector<double> *pdq;	// pointer to velocity vector in process
	vector<double> *pddq;	// pointer to acceleration vector in process
	
	//***** Juan Luis
	vector<double> dqHalf;	// pointer to an auxiliary velocity vector in process
	
	vector<double> *pqConv;	// pointer to coverged position vector in process
	vector<double> *pdqConv;	// pointer to coverged velocity vector in process

	vector <double> ddq_n_1_const;	// vector of constant part of the acceleration	(for implicit integrators)
	vector <double> dq_n_1_const;	// vector of constant part of the velocity	(for implicit integrators)

	// history for multistep integrators
	vector <double> a;		// auxiliary variable for alpha generalized integrator

	vector <double> q_n;	// position vector of the n-th step
	vector <double> q_n1;	// position vector of the n-1 step
	vector <double> q_n2;	// position vector of the n-2 step
	vector <double> q_n3;	// position vector of the n-3 step
	vector <double> q_n4;	// position vector of the n-4 step	

	vector <double> dq_n;	// veloctiy vector of the n-th step	
	vector <double> dq_n1;	// veloctiy vector of the n-th step	
	vector <double> dq_n2;	// veloctiy vector of the n-2 step		
	vector <double> dq_n3;	// veloctiy vector of the n-3 step		
	vector <double> dq_n4;	// veloctiy vector of the n-4 step

	vector <double> ddq_n;	// acceleration vector of the n-th step	
	vector <double> ddq_n1;	// acceleration vector of the n-th step	
	vector <double> ddq_n2;	// acceleration vector of the n-2 step		
	vector <double> ddq_n3;	// acceleration vector of the n-3 step		
	vector <double> ddq_n4;	// acceleration vector of the n-4 step		
		

public:
	Integrator();
	Integrator(string,double, Simulation*, map<string, double, less<string> >&);
	~Integrator(){};

//	void initialize(double h);
//	void setVariables(string tp);
	void setPartials(double h,string tp); 	// calculate the partial derivative df/q_n_1 and df/dq_n_1
	double getPartial_dq();			// returns df/q_n_1
	double getPartial_ddq();		// returns df/dq_n_1

		void integrate(	double time,		// starts the integration
			int timeFlag,
			int numStep);

	// Implicit integrators

	void alphaGen(double time, int timeFlag);
	void newmark(double time, int timeflag);
	void midpoint(double time, int timeflag);
    void consistent(double time, int timeflag);

	// BDF family
	void bdf_1(double time, int timeflag);
	void bdf_2(double time, int timeflag);
	void bdf_3(double time, int timeflag);
	void bdf_4(double time, int timeflag);
	void bdf_5(double time, int timeflag);

	// Adams - Moulton family

	void am_1(double time, int timeflag);
	void am_2(double time, int timeflag);
	void am_3(double time, int timeflag);
	void am_4(double time, int timeflag);
	void am_5(double time, int timeflag);
	

	// Explicit integrators

	// Adams - Bashforth family

	void ab_1(double time, int timeflag);
	void ab_2(double time, int timeflag);
	void ab_3(double time, int timeflag);
	void ab_4(double time, int timeflag);
	void ab_5(double time, int timeflag);

	// Runge Kutta family
	void rk_1(double time);
	void rk_2(double time);
	void rk_3(double time);
	void rk_4(double time);

	// Central differences
	void cd(double time, int);
	
	/** Virtual functions from base */


	/** Local functions */
	
	/** Friend functions */
	friend void printSTLVector(vector<double>& v);
};

#endif
